//Copyright (c) 2006-2007 Microsoft Corporation.  All rights reserved
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Xml;

using InvocationFramework.Common;
using InvocationFramework.Common.Exceptions;
using InvocationFramework.Common.Instrumentation;
using InvocationFramework.Common.Interfaces;
using InvocationFramework.Common.Library;
using InvocationFramework.Common.Resources;

namespace InvocationFramework.Adapters.EnterpriseServices
{
    /// <summary>
    /// </summary>
    /// <author>Rodolfo Finochietti 08/12/2006 20.45</author>
    public class ServicedComponentAdapter : IServiceAdapter
    {
        #region Private Vars

        private Dictionary<string, List<string>> _services;

        #endregion

        #region Constructors

        public ServicedComponentAdapter( ) { }

        #endregion

        #region IServiceAdapter Members

        private string _id;

        public string Id
        {
            get
            {
                return _id;
            }
        }

        private bool _initialized;

        public bool Initialized
        {
            get
            {
                return _initialized;
            }
        }

        public void Init( string id, XmlNode configuration )
        {
            if ( !_initialized )
            {
                try
                {
                    if ( String.IsNullOrEmpty( id ) )
                        throw new ArgumentNullException( "id", String.Format( CultureInfo.InvariantCulture, Texts.ServicedComponentAdapterArgumentNull, "id" ) );

                    _id = id;

                    _services = COMPlusHelper.GetComponents( );
                    
                    _initialized = true;

                    TraceHelper.Verbose( String.Format( CultureInfo.InvariantCulture, Texts.ServicedComponentAdapterInitTrace, "" ) );
                }
                catch ( Exception ex )
                {
                    TraceHelper.Error( ex, Texts.ServicedComponentAdapterInitError );
                    throw;
                }
            }
        }

        public bool IsServiceAvailable( string serviceName )
        {
            if ( !_initialized )
                throw new InvocationFrameworkException( Texts.ServicedComponentAdpaterNotInitialized );

            return _services.ContainsKey( serviceName );
        }

        public bool IsServiceOperationAvailable( string serviceName, string operationName )
        {
            if ( !_initialized )
                throw new InvocationFrameworkException( Texts.ServicedComponentAdpaterNotInitialized );

            if ( IsServiceAvailable( serviceName ) )
                return _services[ serviceName ].Contains( operationName );
            else            
                return false;
        }

        public string[] GetMostRequestedServices( )
        {
            if ( !_initialized )
                throw new InvocationFrameworkException( Texts.ServicedComponentAdpaterNotInitialized );

            return null;
        }

        public object Execute( string serviceName, string operationName, ContextDictionary context, params object[] parameters )
        {
            if ( !_initialized )
                throw new InvocationFrameworkException( Texts.ServicedComponentAdpaterNotInitialized );

            if ( !IsServiceAvailable( serviceName ) )
                throw new InvocationFrameworkException( String.Format( CultureInfo.InvariantCulture, Texts.ServicedComponentAdapterServiceNotFound, serviceName ) );

            if ( !IsServiceOperationAvailable( serviceName, operationName ) )
                throw new InvocationFrameworkException( String.Format( CultureInfo.InvariantCulture, Texts.ServicedComponentAdapterOperationNotFound, serviceName, operationName ) );

            try
            {
                return COMPlusHelper.InvokeMethod( serviceName, operationName, parameters );
            }
            catch ( Exception ex )
            {
                if ( ex.InnerException == null )
                    throw;
                else
                    throw ex.InnerException;
            }
        }

        #endregion
    }
}